package com.kede.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.kede.pay.annotation.PayNotifyHandler;
import com.kede.pay.chain.IHandlerNotify;
import com.kede.pay.config.MyWechatPay2Validator;
import com.kede.pay.config.WxPayConfig;
import com.kede.pay.pojo.NotifyPOJO;
import com.kede.pay.service.ConfigService;
import com.kede.pay.service.IPayNotifyService;
import com.kede.pay.util.AesUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.http.HttpHeaders;
import com.wechat.pay.java.core.notification.Notification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author:Pr.li
 * @Date: create in 2023/6/26 22:09
 */
@Slf4j
@Service
public class PayNotifyService implements IPayNotifyService , ApplicationContextAware {

    @Resource
    private ConfigService configService;

    @Resource
    private RSAAutoCertificateConfig config;

    @Resource
    private WxPayConfig wxPayConfig;



    @Override
    public Map<String,String> Vail(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map){

        String body = JSONObject.toJSONString(map);
        HttpHeaders httpHeaders = new HttpHeaders();
        Enumeration<String> headerNames = request.getHeaderNames();
        httpHeaders.addHeader(MyWechatPay2Validator.REQUEST_ID,map.get("id").toString());
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            String value = request.getHeader(key);
            httpHeaders.addHeader(key, value);
        }
        log.debug("支付回调httpHeaders==={}", httpHeaders);
        MyWechatPay2Validator myWechatPay2Validator = new MyWechatPay2Validator(config.createVerifier());
        if (!myWechatPay2Validator.validate(httpHeaders, body)) {
            log.error("验签不通过");
            return notifyFail(response);
        }
        Notification notification = JSONObject.parseObject(body, Notification.class);
        AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
        com.wechat.pay.java.core.notification.Resource resource = notification.getResource();
        String s = null;
        try {
            s = aesUtil.decryptToString(resource.getAssociatedData().getBytes(), resource.getNonce().getBytes(), resource.getCiphertext());
            NotifyPOJO notifyPOJO = JSONObject.parseObject(s, NotifyPOJO.class);
            String tag = notifyPOJO.getOut_trade_no().substring(0, 3);
            handlerNotifies.forEach(iHandlerNotify -> {
                try {
                    if (iHandlerNotify.match(tag)) {
                        iHandlerNotify.doHandler(notifyPOJO);
                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                }

            });
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.debug("decryptToString=={}", s);
        return notifyOk(response);
    }


    public static Map<String,String> notifyOk(HttpServletResponse response){
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("code","SUCCESS");
        resultMap.put("message","成功");
        response.setStatus(200);
        return resultMap;
    }

    public static Map<String,String> notifyFail(HttpServletResponse response){
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("code","FAIL");
        resultMap.put("message","失败");
        response.setStatus(500);
        return resultMap;
    }

    private static ArrayList<IHandlerNotify> handlerNotifies= new ArrayList<>();


    public static void main(String[] args) {
//        String format = offsetDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayNotifyHandler.class);
        beansWithAnnotation.entrySet().forEach(stringObjectEntry -> {
            handlerNotifies.add((IHandlerNotify)stringObjectEntry.getValue());
        });
    }
}
